package com.lmh.graphdisease.utils;


import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.lmh.graphdisease.utils.ACKMPTree.ACTree;
import com.lmh.graphdisease.vo.FeatureWordsVO;
import com.lmh.graphdisease.vo.QuestionWordsVO;
import org.ahocorasick.trie.Emit;
import org.ahocorasick.trie.Trie;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author lmh
 * @desc 问题分析类，包括问题解析、分类、关键词提取等
 * @date 2023/3/18
 */
public class QuestionUtil {

    private static String jsonPath = "src/main/java/com/lmh/graphdisease/utils/dict/questionWords.json";

    private static String featurePathcheck = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/check.txt";
    private static String featurePathdeny = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/deny.txt";
    private static String featurePathdepartment = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/department.txt";
    private static String featurePathdisease = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/disease.txt";
    private static String featurePathdrug = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/drug.txt";
    private static String featurePathfood = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/food.txt";
    private static String featurePathproducer = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/producer.txt";
    private static String featurePathsymptom = "src/main/java/com/lmh/graphdisease/utils/dict/FeatureWords/symptom.txt";

    private static QuestionWordsVO questionWordsVO;
    private static FeatureWordsVO featureWordsVO;

    /**
     *@author lmh
     *@date 2023/3/23
     *@desc 从json文件中获取问句疑问词，把所有的问句形式穷举
     */
    public static QuestionWordsVO getWordFromJSON(){
        File file = new File(jsonPath);
        String fileStr = null;
        try {
            fileStr = FileUtils.readFileToString(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject jsonObject = JSON.parseObject(fileStr);
        questionWordsVO = new QuestionWordsVO();

        JSONArray jsonArray1 = jsonObject.getJSONArray("symptomWords");
        List<String> symptomWordList = JSON.parseObject(jsonArray1.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setSymptomWords(symptomWordList);

        JSONArray jsonArray2 = jsonObject.getJSONArray("causeWords");
        List<String> causeWordList = JSON.parseObject(jsonArray2.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setCauseWords(causeWordList);

        JSONArray jsonArray3 = jsonObject.getJSONArray("acompanyWords");
        List<String> accompanyWordList = JSON.parseObject(jsonArray3.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setAcompanyWords(accompanyWordList);

        JSONArray jsonArray4 = jsonObject.getJSONArray("foodWords");
        List<String> foodWordList = JSON.parseObject(jsonArray4.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setFoodWords(foodWordList);

        JSONArray jsonArray5 = jsonObject.getJSONArray("drugWords");
        List<String> drugWords = JSON.parseObject(jsonArray5.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setDrugWords(drugWords);

        JSONArray jsonArray6 = jsonObject.getJSONArray("preventWords");
        List<String> preventWords = JSON.parseObject(jsonArray6.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setPreventWords(preventWords);

        JSONArray jsonArray7 = jsonObject.getJSONArray("lasttimeWords");
        List<String> lasttimeWords = JSON.parseObject(jsonArray7.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setLasttimeWords(lasttimeWords);

        JSONArray jsonArray8 = jsonObject.getJSONArray("curewayWords");
        List<String> curewayWords = JSON.parseObject(jsonArray8.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setCurewayWords(curewayWords);

        JSONArray jsonArray9 = jsonObject.getJSONArray("cureprobWords");
        List<String> cureprobWords = JSON.parseObject(jsonArray9.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setCureprobWords(cureprobWords);

        JSONArray jsonArray10 = jsonObject.getJSONArray("easygetWords");
        List<String> easygetWords = JSON.parseObject(jsonArray10.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setEasygetWords(easygetWords);

        JSONArray jsonArray11 = jsonObject.getJSONArray("checkWords");
        List<String> checkWords = JSON.parseObject(jsonArray11.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setCheckWords(checkWords);

        JSONArray jsonArray12 = jsonObject.getJSONArray("belongWords");
        List<String> belongWords = JSON.parseObject(jsonArray12.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setBelongWords(belongWords);

        JSONArray jsonArray13 = jsonObject.getJSONArray("cureWords");
        List<String> cureWords = JSON.parseObject(jsonArray13.toJSONString(),new TypeReference<List<String>>(){});
        questionWordsVO.setCureWords(cureWords);

        return questionWordsVO;
    }

    /**
     *@author lmh
     *@date 2023/3/23
     *@desc 从TXT文件中加载特征词，并且形成FeatureWordsVO 便于之后形成ACtree
     */
    public static FeatureWordsVO getFeatureWordsFromTXT(){
        featureWordsVO = new FeatureWordsVO();
        File file1 = new File(featurePathcheck);
        featureWordsVO.setCheckWords(FileUtil.readLines(file1, StandardCharsets.UTF_8));
        File file2 = new File(featurePathdeny);
        featureWordsVO.setDenyWords(FileUtil.readLines(file2,StandardCharsets.UTF_8));
        File file3 = new File(featurePathdepartment);
        featureWordsVO.setDepartmentWords(FileUtil.readLines(file3,StandardCharsets.UTF_8));
        File file4 = new File(featurePathdisease);
        featureWordsVO.setDiseaseWords(FileUtil.readLines(file4,StandardCharsets.UTF_8));
        File file5 = new File(featurePathdrug);
        featureWordsVO.setDrugWords(FileUtil.readLines(file5,StandardCharsets.UTF_8));
        File file6 = new File(featurePathfood);
        featureWordsVO.setFoodWords(FileUtil.readLines(file6,StandardCharsets.UTF_8));
        File file7 = new File(featurePathproducer);
        featureWordsVO.setProducerWords(FileUtil.readLines(file7,StandardCharsets.UTF_8));
        File file8 = new File(featurePathsymptom);
        featureWordsVO.setSymptomWords(FileUtil.readLines(file8,StandardCharsets.UTF_8));
        Map<String,String> curWordsDict = new HashMap<>();
        for (String s:featureWordsVO.getDiseaseWords()){
            curWordsDict.put(s,"disease");
        }
        for (String s:featureWordsVO.getCheckWords()){
            curWordsDict.put(s,"check");
        }
        for (String s:featureWordsVO.getFoodWords()){
            curWordsDict.put(s,"food");
        }
        for (String s:featureWordsVO.getDrugWords()){
            curWordsDict.put(s,"drug");
        }
        for (String s:featureWordsVO.getDepartmentWords()){
            curWordsDict.put(s,"department");
        }
        for (String s:featureWordsVO.getProducerWords()){
            curWordsDict.put(s,"producer");
        }
        for (String s:featureWordsVO.getSymptomWords()){
            if(!featureWordsVO.getDiseaseWords().contains(s)){
                curWordsDict.put(s,"symptom");
            }
        }
        featureWordsVO.setWordsDict(curWordsDict);
        return featureWordsVO;
    }

    /**
     *@author lmh
     *@date 2023/3/23
     *@desc 构建疾病领域ACtree,本质上构造了一个AC自动机，方便加速匹配
     */
    public static Trie buildACTreeFromVO(FeatureWordsVO featureWordsVO){
        List<String> allWords = new ArrayList<>();
        allWords.addAll(featureWordsVO.getDiseaseWords());
        allWords.addAll(featureWordsVO.getSymptomWords());
        allWords.addAll(featureWordsVO.getDepartmentWords());
        allWords.addAll(featureWordsVO.getCheckWords());
        allWords.addAll(featureWordsVO.getFoodWords());
        allWords.addAll(featureWordsVO.getDrugWords());
        allWords.addAll(featureWordsVO.getProducerWords());
//        System.out.println(allWords.size());
        //使用关键词List构建Trie管道，使用Trie（字典树）数据结构
        Trie trie = Trie.builder().addKeywords(allWords).build();
//        String myMsg = "我有咳嗽，应该是后发性白内障,应该怎么治?";
//        //调用解析方法保存结果到emits集合中
//        Collection<Emit> emits = trie.parseText(myMsg);
//
//        System.out.println(emits.size());
//        for (Emit emit:emits){
//            //关键词出现的初始位置
//            System.out.print(emit.getStart());
//            //关键词出现的末尾
//            System.out.print(emit.getEnd());
//            //关键词
//            System.out.print(emit.getKeyword());
//        }
        return trie;
    }

    /**
     *@author lmh
     *@date 2023/3/23
     *@desc 根据ACTree、用户问题、词类型字典形成最后的字典map，
     */
    public static Map<String,String> useACTreeToQuestion(Trie trie,FeatureWordsVO featureWordsVO,String question){
        //{“苯中毒”:"disease","头疼","symptom"}这种数据
        Map<String,String> results = new HashMap<>();

        //关键词类型词典
        Map<String ,String> keyWordsDict = featureWordsVO.getWordsDict();

//        Trie trie = buildACTreeFromVO(featureWordsVO);
        Collection<Emit> emits = trie.parseText(question);
        //首先处理emits数据，去除“813后发性白内障1113白内障”这种冲突，保留较长的那个str
        int preBeginIndex = 0;
        int preEndIndex = 0;
        String preName = null;
        for (Emit emit:emits){
            if(preBeginIndex == 0 && preEndIndex == 0){//初始化
                preBeginIndex = emit.getStart();
                preEndIndex = emit.getEnd();
                String curWords = emit.getKeyword();
                preName = curWords;
                results.put(curWords,keyWordsDict.get(curWords));
                continue;
            }
            //当前元素是前一个元素的子串
            if(emit.getEnd()<=preEndIndex && emit.getStart() >=preBeginIndex){
                continue;
            }else if(emit.getEnd()>=preEndIndex && emit.getStart() <= preBeginIndex){//当前元素涵盖前一个元素
                results.remove(preName);
                continue;
            }else if(emit.getStart() > preEndIndex){
                preBeginIndex = emit.getStart();
                preEndIndex = emit.getEnd();
                String curWords = emit.getKeyword();
                preName = curWords;
                results.put(curWords,keyWordsDict.get(curWords));
            }

        }
        return results;
    }

    /**
     *@author lmh
     *@date 2023/3/23
     *@desc 判断用户问题类型，根据QuestionVO中的词来判断
     */
    public static List<String> getQustionTypes(String question,Map<String,String> questionWords){
        QuestionWordsVO questionWordsVO = getWordFromJSON();
        FeatureWordsVO featureWordsVO = getFeatureWordsFromTXT();
        List<String> questionTypes = new ArrayList<>();
        List<String> types = new ArrayList<>();
        for (String s:questionWords.values()){
            types.add(s);
        }
        //症状
        if(checkWords(questionWordsVO.getSymptomWords(),question) && types.contains("disease")){
            questionTypes.add("disease_symptom");
        }
        if(checkWords(questionWordsVO.getSymptomWords(),question) && types.contains("symptom")){
            questionTypes.add("symptom_disease");
        }
        //原因
        if(checkWords(questionWordsVO.getCauseWords(),question) && types.contains("disease")){
            questionTypes.add("disease_cause");
        }
        //并发症
        if(checkWords(questionWordsVO.getAcompanyWords(),question) && types.contains("disease")){
            questionTypes.add("disease_acompany");
        }
        //推荐食物
        if(checkWords(questionWordsVO.getFoodWords(),question) && types.contains("disease")){
            boolean deny = checkWords(featureWordsVO.getDenyWords(),question);
            if(deny){
                questionTypes.add("disease_not_food");
            }else {
                questionTypes.add("disease_do_food");
            }
        }
        //已知食物找疾病

        //推荐药品
        if(checkWords(questionWordsVO.getDrugWords(),question) && types.contains("disease")){
            questionTypes.add("disease_drug");
        }
        //药品治啥病
        if(checkWords(questionWordsVO.getCureWords(),question) && types.contains("drug")){
            questionTypes.add("drug_disease");
        }
        //疾病要检查啥
        if(checkWords(questionWordsVO.getCheckWords(),question) && types.contains("disease")){
            questionTypes.add("disease_check");
        }
        //已知检查项目查相应疾病

        //症状防御
        if(checkWords(questionWordsVO.getPreventWords(),question) && types.contains("disease")){
            questionTypes.add("disease_prevent");
        }
        //医疗周期
        if(checkWords(questionWordsVO.getLasttimeWords(),question) && types.contains("disease")){
            questionTypes.add("disease_lasstime");
        }
        //治疗方式
        if(checkWords(questionWordsVO.getCurewayWords(),question) && types.contains("disease")){
            questionTypes.add("disease_cureway");
        }
        //治愈可能行
        if(checkWords(questionWordsVO.getCureprobWords(),question) && types.contains("disease")){
            questionTypes.add("disease_cureprob");
        }
        //易感染人群
        if(checkWords(questionWordsVO.getEasygetWords(),question) && types.contains("disease")){
            questionTypes.add("disease_easyget");
        }

        if(questionTypes.size() == 0 && types.contains("disease")){
            questionTypes.add("disease_desc");
        }
        if(questionTypes.size() == 0 && types.contains("symptom")){
            questionTypes.add("symptom_disease");
        }

        return questionTypes;
    }

    /**
     *@author lmh
     *@date 2023/3/25
     *@desc 构建实体节点，即将所有同类型的实体放在一个list里
     */
    public static Map<String,List<String>> getEntityDict(Map<String,String> wordDict){
        Map<String,List<String>> result = new HashMap<>();
        String curType = "";

        for (String key:wordDict.keySet()){
            curType = wordDict.get(key);
            //已经有该类别
            if(result.containsKey(curType)){
                List<String> curTemp = result.get(curType);
                curTemp.add(key);
                result.put(curType,curTemp);
            }else {//目前没有该类别
                List<String> curTemp = new ArrayList<>();
                curTemp.add(key);
                result.put(curType,curTemp);
            }
        }
        return result;
    }


    /**
     *@author lmh
     *@date 2023/3/26
     *@desc 从Map、List类型数据转化到数据库查询语言,选择查询需要的属性或节点
     * map:{disease=[苯中毒, 多动症, 小儿麻痹症]}
     * list:["disease_cureprob",...]
     */
    public static String getSqls(Map<String,List<String>> allWordsDict,List<String> sqlTypes){


        return "";
    }






    public static boolean checkWords(List<String> lists,String question){
        for (String s:lists){
            if(s!="" && s !=null && question.contains(s)){
                return true;
            }
        }
        return false;
    }


}
